package com.idea.relax.log.publisher;


import com.idea.relax.log.constant.PropsConstant;
import com.idea.relax.log.event.GeneralLogEvent;
import com.idea.relax.log.logger.LogLevel;
import com.idea.relax.log.logger.RelaxLogger;
import com.idea.relax.log.model.GeneralLogModel;
import com.idea.relax.log.support.AppInfoProvider;
import com.idea.relax.log.support.RequestMetadata;
import com.idea.relax.log.support.utils.WebUtil;
import lombok.AllArgsConstructor;
import org.springframework.context.ApplicationEvent;

/**
 * @className: GeneralLogPublisher
 * @description: 通用日志事件发布者
 * @author: salad
 * @date: 2022/6/3
 **/
@AllArgsConstructor
public class GeneralLogPublisher implements ILogPublisher {

    private final ApplicationEvent event;

    private static final String RELAX_LOGGER_NAME = RelaxLogger.class.getName();


    public static GeneralLogPublisher build(String logId, String logData,
                                            LogLevel logLevel, RequestMetadata rmd) {
        GeneralLogModel model = new GeneralLogModel();
        model.setLogId(logId);
        model.setLogData(logData);
        model.setLogLevel(logLevel.getLevel());
        model.setRequestTime(rmd.getRequestTime());
        model.setVisitorIp(rmd.getVisitorIp());
        model.setRequestUri(rmd.getRequestUri());
        model.setRequestMethod(rmd.getRequestMethod());
        model.setRequestParams(rmd.getRequestParams());
        model.setUserAgent(rmd.getUserAgent());
        return commonBuild(model);
    }


    public static GeneralLogPublisher build(String logId, String logData, LogLevel logLevel) {
        GeneralLogModel model = new GeneralLogModel();
        model.setLogId(logId);
        model.setLogData(logData);
        model.setLogLevel(logLevel.getLevel());
        AppInfoProvider.appendRequestInfo(WebUtil.getRequest(), model);
        return commonBuild(model);
    }

    private static GeneralLogPublisher commonBuild(GeneralLogModel model){
        Thread thread = Thread.currentThread();
        StackTraceElement[] trace = thread.getStackTrace();
        String methodClass;
        String methodName;
        if (trace.length < PropsConstant.STACK_TRACE_ELEMENT_INDEX) {
            methodClass = "unknown";
            methodName = "unknown";
        } else if (RELAX_LOGGER_NAME.equals(trace[PropsConstant.STACK_TRACE_ELEMENT_INDEX - 1].getClassName())){
            methodClass = trace[PropsConstant.STACK_TRACE_ELEMENT_INDEX].getClassName();
            methodName = trace[PropsConstant.STACK_TRACE_ELEMENT_INDEX].getMethodName();
        }else {
            methodClass = trace[1].getClassName();
            methodName = trace[1].getMethodName();
        }
        model.setMethodClass(methodClass);
        model.setMethodName(methodName);
        Wrapper<GeneralLogModel> wrapper = new Wrapper<>(model);
        return new GeneralLogPublisher(new GeneralLogEvent(wrapper));
    }

    @Override
    public void publish() {
        LogEventPublisher.publish(event);
    }

}
